package org.springblade.modules.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.common.cache.DictCache;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.enums.ChatGroupRobotEnum;
import org.springblade.modules.admin.service.IChatGroupService;
import org.springblade.modules.notice.service.IBizMsgConfigService;
import org.springblade.modules.system.dto.ReportConfig;
import org.springblade.modules.system.entity.Dict;
import org.springblade.modules.system.enums.DayType;
import org.springblade.modules.system.vo.config.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.modules.system.mapper.TenantConfigMapper;
import org.springblade.modules.system.entity.TenantConfig;
import org.springblade.modules.system.service.TenantConfigService;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.*;

@Service
public class TenantConfigServiceImpl extends ServiceImpl<TenantConfigMapper, TenantConfig> implements TenantConfigService{

	@Lazy
	@Autowired
	private IChatGroupService chatGroupService;
	@Lazy
	@Autowired
	private IBizMsgConfigService bizMsgConfigService;

	private static final String TENANT_CONFIG = "tenant_config";

	@Override
	public TenantConfig getTenantConfig(String tenantId) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(tenantId);
		List<Dict> dictList = DictCache.getList(TENANT_CONFIG);
		if(ObjectUtil.isEmpty(tenantConfig)){
			tenantConfig = new TenantConfig();
		}
		Map<String,Object> configMap = tenantConfig.getConfig();
		if(ObjectUtil.isEmpty(configMap)){
			configMap = new HashMap<>();
		}
		Map<String, Object> finalConfigMap = configMap;
		dictList.forEach(e -> {
			if(!finalConfigMap.containsKey(e.getDictKey())){
				finalConfigMap.put(e.getDictKey(),e.getDictValue());
			}
		});
		RescueScreenConfig rescueScreenConfig = tenantConfig.getRescueScreenConfig();
		if (Func.isNull(rescueScreenConfig)){
			rescueScreenConfig = new RescueScreenConfig();
			tenantConfig.setRescueScreenConfig(rescueScreenConfig);
		}
		AlarmLabelConfig alarmLabelConfig = tenantConfig.getAlarmLabelConfig();
		if (Func.isNull(alarmLabelConfig)){
			alarmLabelConfig = new AlarmLabelConfig();
			tenantConfig.setAlarmLabelConfig(alarmLabelConfig);
		}
		if(Func.isEmpty(tenantConfig.getReportConfig())){
			ReportConfig reportConfig = new ReportConfig();
			reportConfig.setWxOpenOrNot(1);
			reportConfig.setWxNumType(1);
			tenantConfig.setReportConfig(reportConfig);
		}
		if (Func.isEmpty(tenantConfig.getZgRedeployConfig())){
			ZgRedeployConfig zgRedeployConfig = new ZgRedeployConfig();
			zgRedeployConfig.setRedeployDays(7);
			zgRedeployConfig.setApproverUsers(new ArrayList<>());
			zgRedeployConfig.setUserAndRoles(new ArrayList<>());
			tenantConfig.setZgRedeployConfig(zgRedeployConfig);
		}
		if (Func.isEmpty(tenantConfig.getAlarmNotifyConfig())) {
			tenantConfig.setAlarmNotifyConfig(new AlarmNotifyConfig());
		}
		if (Func.isEmpty(tenantConfig.getAlarmConfig())) {
			tenantConfig.setAlarmConfig(new AlarmConfig());
		}
		if (Func.isEmpty(tenantConfig.getRescueSignConfig())) {
			tenantConfig.setRescueSignConfig(new RescueSignConfig());
		}
		// 将 finalConfigMap 与 rescueScreenConfig 合并
		finalConfigMap.putAll(Func.toMap(rescueScreenConfig));
		finalConfigMap.putAll(Func.toMap(alarmLabelConfig));
		tenantConfig.setConfig(finalConfigMap);
		tenantConfig.setTenantId(tenantId);
		tenantConfig.setCreateTime(DateUtil.date());
		tenantConfig.setUpdateTime(DateUtil.date());
		super.saveOrUpdate(tenantConfig);
		return tenantConfig;
	}

	@Override
	public Boolean updateTenantConfig(Map<String, Object> configMap,String tenantId) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(tenantId);
		configMap.forEach((k,v) -> tenantConfig.getConfig().put(k,v));
		tenantConfig.setUpdateTime(DateUtil.date());
		return super.updateById(tenantConfig);
	}

	@Override
	public Boolean updateDetail(@Valid TenantConfig tenantConfig, String tenantId) {
		TenantConfig entity = baseMapper.selectByTenantId(tenantId);
		entity.setScreenRoles(tenantConfig.getScreenRoles());
		RescueScreenConfig rescueScreenConfig = tenantConfig.getRescueScreenConfig();
		// 2024-03-08 新增救援大屏配置
		if(ObjectUtil.isNotEmpty(rescueScreenConfig)){
			entity.setRescueScreenConfig(rescueScreenConfig);
			Map<String, Object> config = entity.getConfig();
			config.putAll(Func.toMap(rescueScreenConfig));
			entity.setConfig(config);
			// 使用Validator进行校验
			Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
			Set<ConstraintViolation<RescueScreenConfig>> violations = validator.validate(rescueScreenConfig);
			if (!violations.isEmpty()) {
				for (ConstraintViolation<RescueScreenConfig> violation : violations) {
					throw new ServiceException(violation.getMessage());
				}
			}
		}else {
			// 当为空时，赋值默认值
			entity.setRescueScreenConfig(new RescueScreenConfig());
		}
		entity.setReportConfig(tenantConfig.getReportConfig());
		return super.updateById(entity);
	}

	@Override
	public Boolean updateZgRedeploy(ZgRedeployConfig zgRedeployConfig, String tenantId) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(tenantId);
		tenantConfig.setZgRedeployConfig(zgRedeployConfig);
		tenantConfig.setUpdateTime(DateUtil.date());
		return super.updateById(tenantConfig);
	}

	@Override
	public Boolean updateAlarmNotify(AlarmNotifyConfig config) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(AuthUtil.getTenantId());
		if (config.getAlarmNotifyEnabled()) {
			if (Func.isEmpty(config.getRounds())) {
				throw new ServiceException("开启困人报警通知，需设置轮次配置");
			}
			List<AlarmNotifyConfig.RoundConfig> rounds = config.getRounds();
			for (AlarmNotifyConfig.RoundConfig round : rounds) {
				if (Func.isEmpty(round.getType())) {
					throw new ServiceException("轮次配置有误");
				}
				if (round.getType() == 2) {
					if (Func.isEmpty(round.getRole()) || Func.isEmpty(round.getRoleAlias()) || Func.isEmpty(round.getScope())) {
						throw new ServiceException("轮次配置有误");
					}
				}
			}
		}

		tenantConfig.setAlarmNotifyConfig(config);
		return super.updateById(tenantConfig);
	}

	@Override
	public Boolean updateAlarm(AlarmConfig config) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(AuthUtil.getTenantId());
		if (config.getTlwAlarm().isEnabled()) {
			if (Func.isEmpty(config.getTlwAlarm().getPeriods())) {
				throw new ServiceException("开启梯联网报警配置，需设置接警时间段");
			}
			TimePeriodValidator.validateNoConflict(config.getTlwAlarm().getPeriods());
		}

		if (config.getAiServiceAlarm().isEnabled()) {
			if (Func.isEmpty(config.getAiServiceAlarm().getPeriods())) {
				throw new ServiceException("开启AI客服报警配置，需设置接警时间段");
			}
			TimePeriodValidator.validateNoConflict(config.getAiServiceAlarm().getPeriods());
		}

		tenantConfig.setAlarmConfig(config);
		return super.updateById(tenantConfig);
	}

	@Override
	public Boolean updateRescueSign(RescueSignConfig config) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(AuthUtil.getTenantId());
		tenantConfig.setRescueSignConfig(config);
		return super.updateById(tenantConfig);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean updateAlarmLabel(AlarmLabelExtConfig config) {
		TenantConfig tenantConfig = baseMapper.selectByTenantId(AuthUtil.getTenantId());
		AlarmLabelConfig alarmLabelConfig = new AlarmLabelConfig();
		BeanUtils.copyProperties(config, alarmLabelConfig);
		tenantConfig.setAlarmLabelConfig(alarmLabelConfig);
		return super.updateById(tenantConfig) && bizMsgConfigService.customChangeStatus(config.getNoticeConfig());
	}

	@Override
	public AiServiceAlarmEnableStatusVO getAiServiceAlarmEnableStatus(String groupId) {
		AiServiceAlarmEnableStatusVO aiStatus = new AiServiceAlarmEnableStatusVO();
		String tenantId = null;
		if (Func.isNotBlank(groupId)) {
			ChatGroup chatGroup = chatGroupService.getOne(Wrappers.<ChatGroup>lambdaQuery().eq(ChatGroup::getGroupId, groupId), false);
			if (chatGroup != null && chatGroup.getStatus() == ChatGroupRobotEnum.ROBOT_STATUS_NORMALLY.getKey() && chatGroup.getPushAllow() == ChatGroupRobotEnum.GROUP_PUSH_OPEN.getKey()) {
				tenantId = chatGroup.getTenantId();
			}
		}
		if (Func.isBlank(tenantId)) {
			return aiStatus;
		}

		TenantConfig tenantConfig = this.getTenantConfig(tenantId);
		AlarmConfig.AiServiceAlarm aiServiceAlarm = tenantConfig.getAlarmConfig().getAiServiceAlarm();
		boolean enabled = aiServiceAlarm.isEnabled() && TimePeriodValidator.isTimeInPeriods(DayType.当日, DateUtil.format(DateUtil.date(), "HH:mm"), aiServiceAlarm.getPeriods());
		aiStatus.setEnabled(enabled);
		aiStatus.setConversationTimeout(aiServiceAlarm.getConversationTimeout());
		return aiStatus;
	}
}
